package com.zzb.framework.config;

import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.util.JdbcUtils;
import com.alibaba.druid.wall.WallConfig;
import com.alibaba.druid.wall.WallFilter;
import com.zzb.framework.frameworkcontroller.interceptor.WebFrameworkInterceptor;
import com.zzb.framework.frameworkcontroller.interceptor.WebFrameworkMenuInterceptor;
import com.zzb.framework.multiplysubmit.MultiplySubmitInterceptor;
import com.zzb.framework.query.GenericQueryDAO;
import com.zzb.framework.query.mysql.MysqlGenericQueryDAO;
import com.zzb.framework.query.postgres.PostgresGenericQueryDAO;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * 框架启动配置
 * Created by zhangzhenbin on 17-6-5.
 */
@Configuration
@ServletComponentScan("com.zzb.framework")
@ComponentScan("com.zzb.framework")
@EnableTransactionManagement
public class FrameworkConfig extends WebMvcConfigurerAdapter  {
    private static final Logger logger = LoggerFactory.getLogger(FrameworkConfig.class);
    @Value("${spring.datasource.url}")
    private String url;
    @Value("${spring.datasource.username}")
    private String username;
    @Value("${spring.datasource.password}")
    private String password;
    @Value("${spring.datasource.validationQuery:SELECT 'X'}")
    private String validationQuery;
    @Value("${spring.datasource.maxActive:10}")
    private Integer maxActive;
    @Value("${spring.datasource.initialSize:1}")
    private Integer initialSize;
    @Value("${spring.datasource.minIdle:1}")
    private Integer minIdle;
    @Value("${spring.datasource.removeAbandonedTimeout:10800}")
    private Integer removeAbandonedTimeout;
    @Value("${spring.datasource.maxWait:10000}")
    private Integer maxWait;
    @Value("${spring.datasource.timeBetweenEvictionRunsMillis:1000}")
    private Integer timeBetweenEvictionRunsMillis;
    @Value("${spring.datasource.poolPreparedStatements:true}")
    private Boolean poolPreparedStatements;
    @Value("${spring.datasource.removeAbandoned:true}")
    private Boolean removeAbandoned;
    @Value("${spring.datasource.logAbandoned:true}")
    private Boolean logAbandoned;
    @Value("${spring.datasource.testWhileIdle:false}")
    private Boolean testWhileIdle;
    @Value("${spring.datasource.maxOpenPreparedStatements:100}")
    private Integer maxOpenPreparedStatements;
    @Value("${spring.mapper.mapper.location:classpath*:mapper/**/*.xml}")
    private String mapperLocation;
    @Value("${spring.database.type:mysql}")
    private String databaseType;
    @Value("${spring.datasource.driverClassName}")
    private String driverClassName;
    @Value("${spring.datasource.filters}")
    private String filters;

    @Bean(name = "dataSource")
    DataSource dataSource() {
        try {
            DruidDataSource dataSource = new DruidDataSource();
            dataSource.setDriverClassName(driverClassName);
            dataSource.setUrl(url);
            dataSource.setUsername(username);
            dataSource.setPassword(password);
            dataSource.setFilters(filters);
            dataSource.setMaxActive(maxActive);
            dataSource.setInitialSize(initialSize);
            dataSource.setMinIdle(minIdle);
            dataSource.setMaxWait(maxWait);
            dataSource.setPoolPreparedStatements(poolPreparedStatements);
            dataSource.setMaxOpenPreparedStatements(maxOpenPreparedStatements);
            dataSource.setValidationQuery(validationQuery);
            dataSource.setTestWhileIdle(testWhileIdle);
            dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
            if(removeAbandonedTimeout > 0){
                dataSource.setRemoveAbandoned(removeAbandoned);
                dataSource.setRemoveAbandonedTimeout(removeAbandonedTimeout);
                dataSource.setLogAbandoned(logAbandoned);
            }
            List<Filter> proxyFilters = new ArrayList<>();
            proxyFilters.add(wallFilter());
            dataSource.setProxyFilters(proxyFilters);
            return dataSource;
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }


    @Bean
    WallFilter wallFilter(){
        WallFilter wallFilter = new WallFilter();
        wallFilter.setDbType(databaseType);
        wallFilter.setConfig(wallConfig());
        return wallFilter;
    }
    @Bean
    WallConfig wallConfig(){
        WallConfig wallConfig = new WallConfig();
        wallConfig.setConditionAndAlwayTrueAllow(true);
        wallConfig.setConditionAndAlwayFalseAllow(true);
        return wallConfig;
    }

    @Bean
    public WebFrameworkInterceptor webFrameworkInterceptor(){return new WebFrameworkInterceptor();}
    @Bean
    public WebFrameworkMenuInterceptor webFrameworkMenuInterceptor(){return new WebFrameworkMenuInterceptor();}
    @Bean
    public MultiplySubmitInterceptor multiplySubmitInterceptor(){return new MultiplySubmitInterceptor();}
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(webFrameworkInterceptor());
        registry.addInterceptor(webFrameworkMenuInterceptor());
        registry.addInterceptor(multiplySubmitInterceptor());
    }


    @Bean
    @Autowired
    public GenericQueryDAO genericQueryDAO(JdbcTemplate jdbcTemplate){
        if(JdbcUtils.MYSQL.equals(databaseType)) return new MysqlGenericQueryDAO(jdbcTemplate);
        if(JdbcUtils.POSTGRESQL.equals(databaseType)) return new PostgresGenericQueryDAO(jdbcTemplate);
        return new MysqlGenericQueryDAO(jdbcTemplate);
    }

}
